﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Reflection;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Soap;

namespace Swaf.Remoting
{
	public class ClientSink : IClientFormatterSink
	{
		protected IClientChannelSink m_nextChannelSink;
		protected IMessageSink m_nextMessageSink;

		public ClientSink(IClientChannelSink next)
		{
			m_nextChannelSink = next;
		}

		#region IMessageSink Members

		public IMessageCtrl AsyncProcessMessage(IMessage msg, IMessageSink replySink)
		{
			throw new NotImplementedException();
		}

		public IMessageSink NextSink
		{
			get { return m_nextMessageSink; }
		}

		public IMessage SyncProcessMessage(IMessage msg)
		{
			IMethodCallMessage mcm = new FlexiTypeMethodCallMessage((IMethodCallMessage)msg);
			BaseTransportHeaders requestHeaders = new BaseTransportHeaders();
			MethodBase methodBase = mcm.MethodBase;
			requestHeaders["SOAPAction"] = '"' + SoapServices.GetSoapActionFromMethodBase(methodBase) + '"';
			requestHeaders.ContentType = "text/xml; charset=\"utf-8\"";
			requestHeaders["__RequestVerb"] = "POST";

			Stream requestStream = NextChannelSink.GetRequestStream(mcm, requestHeaders);
			if (requestStream == null)
				requestStream = new MemoryStream();

			RemotingSurrogateSelector remSs = new RemotingSurrogateSelector();
			SoapFormatter formatter = new SoapFormatter();
			formatter.Binder = new FlexiSerializationBinder();
			formatter.SurrogateSelector = remSs;
			remSs.UseSoapFormat();
			formatter.Context = new StreamingContext(StreamingContextStates.Other);
			formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
			formatter.FilterLevel = System.Runtime.Serialization.Formatters.TypeFilterLevel.Full;
			Header[] soapHeaders = ServerSink.GetMessagePropertiesAsSoapHeader(msg);
			remSs.SetRootObject(msg);
			//MethodCall c = new MethodCall(msg);
			IMethodMessage message = mcm as IMethodMessage;
			formatter.Serialize(requestStream, message, soapHeaders);
			requestStream.Position = 0;
			TextReader rdr = new StreamReader(requestStream);
			StringBuilder t = new StringBuilder(rdr.ReadToEnd());
			t.Replace("Swaf.Container/test", "Swaf.Container/Swaf");
			t.Replace("test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null", "SwafInterfaces, Version=1.7.1.28013, Culture=neutral, PublicKeyToken=null");
			t.Replace("Swaf.BizObj.basic/test", "Swaf.BizObj.basic/Swaf");
			t.Replace("Swaf/test", "Swaf/Swaf");
			t.Replace("Swaf.BGuid/test", "Swaf.BGuid/Swaf");
			File.WriteAllText(@"d:\dev2009\clientsoap2.xml", t.ToString());
			requestStream = new MemoryStream();
			TextWriter tw = new StreamWriter(requestStream);
			tw.Write(t.ToString());


			ITransportHeaders responseHeaders = null;
			Stream responseStream = new MemoryStream();
			this.m_nextChannelSink.ProcessMessage(message, requestHeaders, requestStream, out responseHeaders, out responseStream);


			Header[] h = new Header[] { new Header("__TypeName", mcm.TypeName), new Header("__MethodName", mcm.MethodName), new Header("__MethodSignature", mcm.MethodSignature) };
			MethodResponse response = new MethodResponse(h, mcm);
			formatter.SurrogateSelector = null;
			formatter.Deserialize(responseStream, new HeaderHandler(response.HeaderHandler));
			return response;
		}

		#endregion

		#region IClientChannelSink Members

		public void AsyncProcessRequest(IClientChannelSinkStack sinkStack, IMessage msg, ITransportHeaders headers, System.IO.Stream stream)
		{
			throw new NotImplementedException();
		}

		public void AsyncProcessResponse(IClientResponseChannelSinkStack sinkStack, object state, ITransportHeaders headers, System.IO.Stream stream)
		{
			throw new NotImplementedException();
		}

		public System.IO.Stream GetRequestStream(IMessage msg, ITransportHeaders headers)
		{
			throw new NotImplementedException();
		}

		public IClientChannelSink NextChannelSink
		{
			get { return m_nextChannelSink; }
		}

		public void ProcessMessage(IMessage msg, ITransportHeaders requestHeaders, System.IO.Stream requestStream, out ITransportHeaders responseHeaders, out System.IO.Stream responseStream)
		{
			throw new NotImplementedException();
		}

		#endregion

		#region IChannelSinkBase Members

		public System.Collections.IDictionary Properties
		{
			get { return null; }
		}

		#endregion
	}

	public class ClientSinkProvider : IClientFormatterSinkProvider
	{
		protected IClientChannelSinkProvider m_next = null;

		public ClientSinkProvider()
		{
		}

		public ClientSinkProvider(IDictionary properties, ICollection providerData)
		{
		}
		#region IClientChannelSinkProvider Members

		public IClientChannelSink CreateSink(IChannelSender channel, string url, object remoteChannelData)
		{
			IClientChannelSink chain = Next.CreateSink(channel, url, remoteChannelData);
			IClientChannelSink sinkFormatter = new ClientSink(chain);
			return sinkFormatter;
		}

		public IClientChannelSinkProvider Next
		{
			get
			{
				return m_next;
			}
			set
			{
				m_next = value;
			}
		}

		#endregion
	}
}
